/**
 * @fileOverview jsamd module lite
 */

var definePool = [],
	dependenciesPool = {},
	modules = {},
	loadQueue = [];
	margs = ["require", "exports", "module"];

// config
var baseUrl = '',
	urlArgs = '',
	paths = {};

/**
 * @see JavaScript 秘密花园#类型.typeof {@link http://bonsaiden.github.com/JavaScript-Garden/zh/#types.typeof}
 */
function is (obj, type) {
	var klass = Object.prototype.toString.call(obj).slice(8, -1);
	return obj !== undefined && obj !== null && klass === type;
}

function getUrl (id) {
	var preurl = (!id.indexOf('/') || !id.indexOf('http')) ? '' : baseUrl;
	
	paths.forEach(function (p) {
		id = id.replace(new Regexp('(^' + p + ')', 'g'), paths[p]);
	});
	return preurl + id + (id.indexOf(".") < 0 ? ".js" : "") + urlArgs;
}

function getParentPath (path) {
	return path.substr(0, path.lastIndexOf("/"));
}

function getArgs (array, obj) {
	Object.keys(obj).forEach(function (k) {

	});
}

function dfModule (id, define, noExports, module) {
	
	if(~margs.indexOf(id)) {
		return id;
	}

	module = modules[id] = define || modules[id];

	return (module && module.exports) ? (noExports ? module : module.exports) : null;

}

function resolveSysbol (id, dependencies) {
	var d, dep;
	dependenciesPool[id] = dependencies;
	dependencies.forEach(function(d) {
		dep = dependenciesPool[d];
		dep.forEach(function(_d){
			if(!~dependencies.indexOf(-d)){
				// if _d === d than create empty module
				_d !== d ? dependencies.push(_d) : dfModule(d, {exports : {}});
			}
		});
	});
}

function resolvePath (path, context) {
	context = ~path.indexOf('.') ? context : '';
}

function normalize (path) {
	var temp;
	path = path.replace(/(^|[^\.])(\.\/)/g, "$1");

	while (temp !== path) {
		temp = path;
		path = path.replace(/([\w,\-]*[\/]{1,})([\.]{2,}\/)/g, "");
	}

	return path.replace(/(\/{2,})/g, "/");
}

function checkLoadQueue () {
	var q, len = loadQueue.length;
	for (var i = len - 1; i >= 0 && (q = loadQueue[i]) ; i--) {
		// TODO
	};
}

/**
 * @see the idea form seajs, you can visit {@link https://github.com/seajs/seajs} for more
 * @see The Asynchronous Module Definition (**AMD**) API {@link https://github.com/amdjs/amdjs-api/wiki/AMD} 
 */
function define (id, dependencies, factory, /** private param*/ isInQed, isLoaded) {
	var isFn = is(factory, 'Function');
	// id is not string
	if(!is(id,'String')) {
		factory = dependencies;
		dependencies = id;
		id = 0;
		definePool.push([dependencies, factory]);
		return;
	}
	
	// dependencies is not Array
	if(!is(dependencies,'Array')) {
		factory = dependencies; // 
		dependencies = []; // reset dependencies
	}

	if(!isInQed) {
		definePool.push(0);
	}

	parentPath = getParentPath(id);

	// factory.length is the function arguments length
	if(!dependencies.length && factory.length && isFn) {
		// be careful the regexp
		factory.toString()
				.replace(/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, "")
				.replace(/(?:require)\(\s*["']([^'"\s]+)["']\s*\)/g,

					function ($0, $1) {
						if (dependencies.indexOf($1) < 0) {
							dependencies.push($1);
						}
					}
				);
		 dependencies = (margs.slice(0,factory.length)).concat(dependencies);
	}

	if(dependencies.length && !isLoaded) {
		resolveSysbol(id, dependencies)

		require(dependencies, function () {
			// loaded call define again
			define(id, Array.prototype.slice.call(arguments, 0), factory, 1, 1);
		});

		return;
	}

	module = dfModule(id, 0, 1) || {exports: {}}; // get the empty module

	module.id = id;
	module.url = getUrl(id);
	
	if(isFn) {
		var fnArgs = getArgs(dependencies.length ? dependencies : (margs.slice(0, factory.length)));
		 module.exports = factory.apply(factory, fnArgs) || module.exports;
	} else {
		module.exports = factory;
	}

	// overwrite module
	dfModule(id, module);

	delete dependenciesPool[id];

	checkLoadQueue();
}

function require (ids, callback, context) {
	if(!callback) {
		ids = resolvePath
	}
}